package Or

import (
	"context"
	"db2s/global"
	"db2s/parDef"
	"db2s/ref"
	"errors"
	"fmt"
	"regexp"
	"strings"
	"time"
)

type columnMeta struct {
	DatabaseName  string `json:"databaseName"`
	TableName     string `json:"tableName"`
	ColumnName    string `json:"columnName"`
	ColumnType    string `json:"columnType"` //原始的数据类型，不带长度的
	ColumnSeq     string `json:"columnSeq"`
	IsNull        string `json:"isNull"` //
	Charset       string `json:"charset"`
	CollationName string `json:"collationName"`
	ColumnComment string `json:"columnComment"`
	ColumnDefault string `json:"columnDefault"`
	DataType      string `json:"dataType"` //处理过的数据类型，带长度的
	DataLength    int64  `json:"dataLength"`
	CharLength    int64  `json:"charLength"`
	DataPrecision int64  `json:"dataPrecision"`
	DataScale     int64  `json:"dataScale"`
	Invisible     bool   `json:"invisible"`
	AutoIncrement bool
}

func colMetaMapInit(s parDef.ColumnMeta) parDef.ColMetaMapS {
	return parDef.ColMetaMapS{
		DatabaseName:     s.DatabaseName,
		TableName:        s.TableName,
		ColumnName:       s.ColumnName,
		Charset:          s.Charset,
		CollationName:    s.CollationName,
		ColAutoIncrement: s.AutoIncrement,
		Invisible:        s.Invisible,
		ColumnComment:    s.ColumnComment,
		ColumnSeq:        s.ColumnSeq,
	}
}

func charTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "char"
	switch strings.ToUpper(m.ColumnType) {
	case "CHAR", "NCHAR":
		/*
			定义长度: CHAR 类型需要在定义时指定长度,最大长度为 2000 个字符。例如, CHAR(10) 表示最多可以存储 10 个字符的字符串。
			存储空间: CHAR 类型会占用固定的存储空间,即定义的长度个字节。例如, CHAR(10) 类型会占用 10 个字节的存储空间。
		*/
		res.Type.ColTypeMap = fmt.Sprintf("char(show)")
		res.Type.MaxValue = 4000
		res.Type.ShowValue = m.CharLength
		res.Type.UseByte = m.CharLength
	case "VARCHAR2", "NVARCHAR2":
		/*
			定义长度: VARCHAR 类型需要在定义时指定最大长度,最大长度为 4000 个字符。例如, VARCHAR2(50) 表示最多可以存储 50 个字符的字符串。
		*/
		res.Type.ColTypeMap = fmt.Sprintf("varchar(show)")
		res.Type.MaxValue = 4000
		res.Type.Variable = true
		res.Type.ShowValue = m.CharLength
		res.Type.UseByte = m.CharLength
	default:
		err = ref.ErrAddPrintf("charTypeMap", errors.New(fmt.Sprintf("type not match. curry type is %v", m.ColumnType)))
	}
	return
}
func iSVarchar(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	switch strings.ToUpper(m.ColumnType) {
	case "CHAR", "NCHAR", "VARCHAR2", "NVARCHAR2":
		res, err = charTypeMap(m, p)
	default:
		err = ref.ErrAddPrintf("iSVarchar", errors.New(fmt.Sprintf("not match type %v", m.DataType)))
	}
	return
}

/*
numberTypeMap

	在 Oracle 中, NUMBER 类型列的 DATA_LENGTH 属性通常为 22。这里有几点需要解释:
	1):数字精度和标度: Oracle 中的 NUMBER 类型可以存储带小数点的数值。NUMBER 类型有两个属性:精度(PRECISION)和标度(SCALE)。精度指数值可以存储的最大位数,标度指小数点后可以存储的位数。
		默认 NUMBER 类型的长度: 当 NUMBER 类型的精度和标度未指定时,Oracle 会默认使用精度 38,标度 0。这种情况下,DATA_LENGTH 属性会被设置为 22 个字节。
		22 个字节的原因:Oracle 内部使用 16 个字节来存储 38 位精度的数值。另外 6 个字节用于存储附加信息,如正负号、小数位数等。所以默认 NUMBER 类型列的 DATA_LENGTH 属性为 22 个字节。
	2): number(p,s)  如何不指定p和s，则默认为number(38,0);即最大38位整数,如何只指定p，则s默认为0，即整数。例如number(10)，表示10位整数,同时指定p和s，则p必须大于等于s，例如number(10,2)，表示最多10位数字，其中包括两位小数
		s可以是负数，表示小数点左边的位数。例如number(10,-2)表示10位整数，且最多保留到百位
*/
func numberTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	//number(p,s)  如何不指定p和s，则默认为number(38,0);即最大38位整数
	//如何只指定p，则s默认为0，即整数。例如number(10)，表示10位整数
	//同时指定p和s，则p必须大于等于s，例如number(10,2)，表示最多10位数字，其中包括两位小数
	//s可以是负数，表示小数点左边的位数。例如number(10,-2)表示10位整数，且最多保留到百位
	res = p
	res.TypeBelong = "decimal"
	res.Type.ColTypeMap = "decimal(precision,scale)"
	switch {
	case m.DataPrecision == 0 && m.DataScale == 0: //不定长整数位 number、number(*,0)、number(*)
		res.Type.Precision = 40
		res.Type.ColTypeMap = "decimal(max,max)"
	case m.DataPrecision > 0 && m.DataScale == 0:
		res.Type.Precision = m.DataPrecision
	case m.DataPrecision == 0 && m.DataScale > 0: //number(*,5)
		res.Type.Precision = 38
		res.Type.Scale = m.DataScale
	case m.DataPrecision > 0 && m.DataScale > 0 && m.DataPrecision < m.DataScale: //number(10,20)
		res.Type.Precision = m.DataPrecision + m.DataScale
		res.Type.Scale = m.DataScale
	case m.DataPrecision == 0 && m.DataScale < 0: //负数开头，表示只有整数，没有小数。例如：number(*,-2)
		res.Type.Precision = 40
	case m.DataPrecision > 0 && m.DataScale > 0: // number(DataPrecision,Scale)
		res.Type.Precision = m.DataPrecision
		res.Type.Scale = m.DataScale
	case m.DataPrecision > 0 && m.DataScale < 0: //负数开头，表示只有整数，没有小数。例如：number(10,-2)
		res.Type.Precision = m.DataPrecision
	default:
		err = ref.ErrAddPrintf("numberTypeMap", errors.New(fmt.Sprintf("type not match. curry type is %v", m.ColumnType)))
	}
	return
}

/*
FloatTypeRedefine
"FLOAT", "BINARY_FLOAT", "BINARY_DOUBLE": //浮点类型
float 是1~126的二进制长度，位数需要转换成十进制precision =(precision * 0.30103) 向上取整"DOUBLE PRECISION"
binary_float，binary_double 只能存17位有效数字
*/
func floatTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "float"
	res.Type.ColTypeMap = "float(precision)"
	switch strings.ToUpper(m.ColumnType) {
	case "FLOAT":
		/*
			Oracle 的 FLOAT 数据类型可以表示约 1 到 38 位十进制有效数字的原因如下:
				IEEE 754 标准:
					Oracle 的 FLOAT 数据类型遵循 IEEE 754 浮点数标准。
					根据 IEEE 754 标准, 64 位浮点数包含 1 位符号位、11 位指数位和 52 位尾数位。
				尾数位于有效数字位数的关系:
					52 位尾数位理论上可以表示约 2^52 ≈ 4.5e+15 个不同的值。
					但由于浮点数的内部表示方式,实际上只能表示约 15-16 位十进制有效数字。
				Oracle FLOAT 的特点:
					Oracle 的 FLOAT 数据类型支持 1 到 126 位之间的二进制精度。
					当声明为 FLOAT(53) 时,等同于 IEEE 754 标准中的 64 位 double 类型。
					38 位十进制有效数字的原因:
					虽然 FLOAT(53) 只能表示 15-16 位十进制有效数字,但是 Oracle 的 FLOAT 数据类型支持更高的二进制精度。
					当声明为更高的二进制精度,例如 FLOAT(126),这就可以表示约 38 位十进制有效数字。
					综上所述,Oracle 的 FLOAT 数据类型可以表示约 1 到 38 位十进制有效数字,是因为 Oracle 支持更高的二进制精度,超出了 IEEE 754 标准中 64 位浮点数的限制。但这需要以更高的存储空间为代价。对于大多数场景,使用 FLOAT(53) 即可满足需求。
		*/
		if m.DataPrecision > 0 {
			res.TypeBelong = "float"
			res.Type.MaxValue = 23
			res.Type.ShowValue = int64(float64(m.DataPrecision)*0.30103) + 1
		} else {
			res.TypeBelong = "double"
			res.Type.MaxValue = 53
			res.Type.ShowValue = 53
			res.Type.MaxValue = 53
		}
	case "BINARY_FLOAT":
		/*
			BINARY_FLOAT 使用 IEEE 754 标准的单精度浮点数格式进行存储。这种格式包含以下三个部分:  符号位 (1 bit)  指数位 (8 bits)  尾数位 (23 bits)  2^23大约能表示7~8位数字
		*/
		res.TypeBelong = "float"
		res.Type.ShowValue = 23
		res.Type.MaxValue = 23
	case "BINARY_DOUBLE":
		res.TypeBelong = "double"
		res.Type.ShowValue = 53
		res.Type.MaxValue = 53
	default:
		err = ref.ErrAddPrintf("floatTypeMap", errors.New(fmt.Sprintf("type not match. curry type is %v", m.ColumnType)))
	}
	return
}

/*
	rowID是一个 18 字节的 CHAR 类型,它由 6 个部分组成:
	数据文件号(1 byte)
	块号(3 bytes)
	行号(2 bytes)
	检查和(2 bytes)

但是oracle使用base 64编码将18字节的rowID值转换为10个ASCII字符，所以实际存储的时候时，将18字节用base 64编码压缩成10字符，所以all_table_column中data_length显示的是10
*/
func rowIdTypeMap(_ parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "char"
	res.Type.MaxValue = 18
	res.Type.ShowValue = 18
	res.Type.UseByte = 18
	res.Type.ColTypeMap = fmt.Sprintf("char(show)")
	return
}

/*
Oracle内部以二进制的形式存储DATE数据。
它包含了:century(1个字节)、year(1个字节)、month(1个字节)、day(1个字节)、hour(1个字节)、minute(1个字节)、second(1个字节),共7个字节。
*/
func timeTypeMap(_ parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "time"
	res.Type.ColTypeMap = "year-month-day hour:minute:second"
	return
}
func timestampTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "timestamp"
	switch m.DataScale {
	case 0:
		res.Type.ColTypeMap = "year-month-day hour:minute:second"
	case 1:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.milli(1)"
	case 2:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.milli(2)"
	case 3:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.milli(3)"
	case 4:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.micro(1)"
	case 5:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.micro(2)"
	case 6:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.micro(3)"
	case 7:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.nano(1)"
	case 8:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.nano(2)"
	case 9:
		res.Type.ColTypeMap = "year-month-day hour:minute:second.nano(3)"
	}
	if strings.Contains(m.DataType, "WITH TIME ZONE") || strings.Contains(m.DataType, "WITH LOCAL TIME ZONE") {
		res.Type.ColTypeMap = fmt.Sprintf("%v.utc", res.Type.ColTypeMap)
	}
	return
}

/*
常用的文本类型转换。

	long {可变长字符列，最大长度限制是2GB，用于不需要作字符串搜索的长串数据，如果要进行字符搜索就要用varchar2类型。long是一种较老的数据类型，将来会逐渐被BLOB、CLOB、NCLOB等大的对象数据类型所取代。}
	blob\clob\nclob {三种大型对象(LOB)，用来保存较大的图形文件或带格式的文本文件，如MiceSoft Word文档，以及音频、视频等非文本文件，最大长度是4GB。LOB有几种类型，取决于你使用的字节的类型，Oracle 8i实实在在地将这些数据存储在数据库内部保存。可以执行读取、存储、写入等特殊操作。}
*/
func textTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "text"
	res.Type.ColTypeMap = "text"
	switch strings.ToUpper(m.ColumnType) {
	case "LONG":
		/*
			LONG 数据类型是 Oracle 数据库中用于存储大文本数据的一种数据类型。最大长度为 2 GB。这意味着它可以存储最多 2 GB 的文本数据。要换算成字符数,需要考虑字符编码。以 UTF-8 编码为例:1 个英文字符占 1 个字节 1 个中文字符占 3 个字节
			需要注意的是, Oracle 不建议再使用 LONG 数据类型,而是建议使用更新的 CLOB 数据类型。CLOB 数据类型的最大长度为 4 GB,比 LONG 类型增加了一倍的容量。同时 CLOB 在性能、可操作性等方面也更加优秀。
		*/
		res.Type.MaxValue = 2147483648
		res.Type.ShowValue = 2147483648
		res.Type.UseByte = 2147483648
	case "CLOB", "NCLOB":
		res.Type.MaxValue = 4294967295
		res.Type.ShowValue = 4294967295
		res.Type.UseByte = 4294967295
	default:
		err = ref.ErrAddPrintf("textTypeMap", errors.New(fmt.Sprintf("type not match. curry type is %v", m.ColumnType)))
	}
	return
}
func lobTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "lob"
	switch strings.ToUpper(m.ColumnType) {
	case "BLOB":
		res.Type.MaxValue = 4294967296
		res.Type.ShowValue = 4294967296
		res.Type.ColTypeMap = "binary"
		res.Type.UseByte = 4294967296
	case "RAW":
		res.Type.MaxValue = 2000
		res.Type.ShowValue = 2000
		res.Type.ColTypeMap = "binary(show)"
		res.Type.UseByte = 2000
	case "LONG RAW":
		res.Type.MaxValue = 2147483648
		res.Type.ShowValue = 2147483648
		res.Type.ColTypeMap = "binary"
		res.Type.UseByte = 2147483648
	default:
		err = ref.ErrAddPrintf("lobTypeMap", errors.New(fmt.Sprintf("type not match. curry type is %v", m.ColumnType)))
	}
	return
}
func gisTypeMap(_ parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	res.TypeBelong = "gis"
	res.Type.ColTypeMap = "geometry"
	return
}
func notISVarchar(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	switch strings.ToUpper(m.ColumnType) {
	case "NUMBER":
		res, err = numberTypeMap(m, p) //case "NUMBER", "DECIMAL", "NUMERIC": //定长数值
	case "FLOAT", "BINARY_FLOAT", "BINARY_DOUBLE":
		res, err = floatTypeMap(m, p)
	case "ROWID", "UROWID":
		res, err = rowIdTypeMap(m, p)
	case "DATE":
		res, err = timeTypeMap(m, p)
	case "TIMESTAMP", "TIMESTAMP WITH TIME ZONE", "TIMESTAMP WITH LOCAL TIME ZONE":
		res, err = timestampTypeMap(m, p)
	case "INTERVAL DAY TO SECOND", "TO_CHAR(SYSDATE,'YYYYMMDD')":
	case "CLOB", "NCLOB", "LONG":
		res, err = textTypeMap(m, p)
	case "BLOB", "LONG RAW", "RAW": //二进制类型
		res, err = lobTypeMap(m, p)
	case "ST_GEOMETRY", "SDO_GEOMETRY":
		res, err = gisTypeMap(m, p)
	default:
		err = ref.ErrAddPrintf("Oracle.notISVarchar", errors.New(fmt.Sprintf("not match type %v", m.DataType)))
	}
	return
}
func colTypeMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	//字符串类型包含char，varchar2,nchar,nvarchar2,clob,nclob
	//只有char,nchar,varchar2,nvarchar2涉及到长度
	//char和nchar是定长的，如果输入的字符串长度小于size，则会用空格填充
	//nLob和lob的char_length=0
	if m.CharLength > 0 || m.CharLength == -1 { //数值类型 和lob类型
		if res, err = iSVarchar(m, p); err != nil {
			err = ref.ErrAddPrintf("colTypeMap", err)
			return
		}
		return
	}
	if res, err = notISVarchar(m, p); err != nil {
		err = ref.ErrAddPrintf("colTypeMap", err)
		return
	}
	return
}
func colNullMap(m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS) {
	//是否允许为null，yes表示为允许，no表示不允许
	res = p
	switch m.IsNull {
	case "Y":
		res.ColNullMap = "YES"
	case "N":
		res.ColNullMap = "NO"
	}
	return
}

func LeftRightSingleQuotationMarks(defaultVal string) (newDefaultVal string) {
	if strings.HasSuffix(defaultVal, "\n") {
		defaultVal = strings.TrimSpace(defaultVal[:len(defaultVal)-1])
	}
	if strings.HasPrefix(defaultVal, "'") && !strings.HasSuffix(defaultVal, "'") && strings.Contains(defaultVal, "'") {
		if n := strings.LastIndex(defaultVal, "'"); n != 0 {
			defaultVal = defaultVal[1:n]
		}
	}
	newDefaultVal = defaultVal
	if strings.HasPrefix(defaultVal, "'") && strings.HasSuffix(defaultVal, "'") {
		newDefaultVal = defaultVal[1 : len(defaultVal)-1]
	}
	newDefaultVal = strings.ReplaceAll(newDefaultVal, "''", "'") //处理单引号转义问题
	if n := strings.Index(newDefaultVal, "--"); n != -1 {
		newDefaultVal = newDefaultVal[:n]
	}
	return
}
func isValidTimeFormat(s string, layout string) (bool, time.Time) {
	t, err := time.Parse(layout, s)
	if err != nil {
		return false, time.Time{}
	}
	return true, t
}
func defaultTimeFunc(ctx context.Context, newDefaultVal string) (colDefaultMap string, err error) {
	var res []string
	var timeFormats = map[string]string{
		"2006":                                    "year",
		"01":                                      "month",
		"02":                                      "day",
		"03":                                      "hour",
		"04":                                      "minute",
		"05":                                      "second",
		"2006-01":                                 "year-month",
		"2006-01-02":                              "year-month-day",
		"15:04":                                   "hour:minute:second",
		"15:04:05":                                "hour:minute:second", // 例: 14:00:00
		"2006-01-02 15":                           "year-month-day hour",
		"2006-01-02 15:04":                        "year-month-day hour:minute",
		"2006-01-02 15:04:05":                     "year-month-day hour:minute:second", // 例: 2023-09-23 14:00:00
		"2006-01-02 15:04:05.9":                   "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.9 PM -07:00":         "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99":                  "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99 PM -07:00":        "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999":                 "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999 PM -07:00":       "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.9999":                "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.9999 PM -07:00":      "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99999":               "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99999 PM -07:00":     "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999999":              "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999999 PM -07:00":    "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.9999999":             "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.9999999 PM -07:00":   "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99999999":            "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.99999999 PM -07:00":  "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999999999":           "year-month-day hour:minute:second",
		"2006-01-02 15:04:05.999999999 PM -07:00": "year-month-day hour:minute:second",
		"20060102":                                "yearMonthDay",
	}
	if res, err = selectFromDual(ctx, fmt.Sprintf("%v\n", newDefaultVal)); err != nil {
		err = ref.ErrAddPrintf("defaultTimeFunc", err)
		return
	}
	for _, v := range res {
		for format, mapFormat := range timeFormats {
			if valid, _ := isValidTimeFormat(strings.ReplaceAll(v, "'", ""), format); valid {
				if strings.Contains(newDefaultVal, "TO_DATE") {
					colDefaultMap = strings.ReplaceAll(v, "'", "")
					return
				}
				colDefaultMap = mapFormat
				return
			}
		}
	}
	if len(colDefaultMap) == 0 {
		err = ref.ErrAddPrintf("defaultTimeFunc", fmt.Errorf("not match time format. curry value is %v", newDefaultVal))
	}
	//[]string{"SYSDATE", "CURRENT_DATE", "CURRENT_TIMESTAMP", "DBTIMEZONE", "SESSIONTIMEZONE", "TO_DATE", "ADD_MONTHS", "MONTHS_BETWEEN", "LAST_DAY", "NEXT_DAY", "TRUNC", "ROUND", "EXTRACT"}
	return
}

// 判断字符串是否是该类型(100)，如果是，则变成100
func regexpMustCompile(str string) string {
	re := regexp.MustCompile(`^\((\d+)\)$`)
	// 查找匹配项
	matches := re.FindStringSubmatch(str)
	// 如果有匹配结果，返回捕获的数字和true
	if len(matches) == 2 {
		return matches[1]
	}
	return str
}
func toDefaultFunc(newDefaultVal string, funcName []string) (exist bool) {
	for _, v := range funcName {
		if strings.Contains(newDefaultVal, v) {
			return true
		}
	}
	return false
}
func colDefaultMap(ctx context.Context, m parDef.ColumnMeta, p parDef.ColMetaMapS) (res parDef.ColMetaMapS, err error) {
	res = p
	switch {
	case toDefaultFunc(strings.TrimSpace(strings.ToUpper(LeftRightSingleQuotationMarks(m.ColumnDefault))), []string{"SYSDATE", "SYSTIMESTAMP", "CURRENT_DATE", "CURRENT_TIMESTAMP", "DBTIMEZONE", "SESSIONTIMEZONE", "TO_DATE", "ADD_MONTHS", "MONTHS_BETWEEN", "LAST_DAY", "NEXT_DAY", "TRUNC", "ROUND", "EXTRACT"}): //处理时间函数
		res.ColDefaultMap, err = defaultTimeFunc(ctx, LeftRightSingleQuotationMarks(m.ColumnDefault))
		return
	case toDefaultFunc(strings.TrimSpace(strings.ToUpper(LeftRightSingleQuotationMarks(m.ColumnDefault))), []string{"SYS_GUID"}):
		res.ColDefaultMap = "sys_guid"
		return
	case toDefaultFunc(strings.TrimSpace(strings.ToUpper(LeftRightSingleQuotationMarks(m.ColumnDefault))), []string{"USER"}):
		res.ColDefaultMap = "current_user"
		return
	case toDefaultFunc(strings.TrimSpace(strings.ToUpper(LeftRightSingleQuotationMarks(m.ColumnDefault))), []string{"USERENV('SESSIONID')"}):
		res.ColDefaultMap = "current_id"
		return
	case strings.HasSuffix(strings.TrimSpace(strings.ToUpper(LeftRightSingleQuotationMarks(m.ColumnDefault))), ".NEXTVAL") && strings.HasPrefix(strings.ToLower(m.ColumnType), "number"):
		res.ColAutoIncrement = true
		return
	default:
		res.ColDefaultMap = regexpMustCompile(LeftRightSingleQuotationMarks(m.ColumnDefault))
		return
	}
}

func (cm ColumnMe) MetaMap(ctx context.Context) (result global.Return, err error) {
	var meta = parDef.GetFuncParameterValue(ctx, parDef.GetMetaParameterValue())
	if meta == nil {
		return
	}
	var res []parDef.ColMetaMapS
	for _, v := range meta.([]parDef.ColumnMeta) {
		var p parDef.ColMetaMapS
		if p, err = colTypeMap(v, colMetaMapInit(v)); err != nil {
			err = ref.ErrAddPrintf("MetaMap", err)
			return
		}
		p = colNullMap(v, p)
		if p, err = colDefaultMap(ctx, v, p); err != nil {
			err = ref.ErrAddPrintf("MetaMap", err)
			return
		}
		p.ColumnSeq = v.ColumnSeq
		res = append(res, p)
	}
	result.Result = res
	return
}
func (cm ColumnMe) ColumnAttributeMapClip(ctx context.Context) (result global.Return, err error) {
	var metaBase MetaBaseInitResult
	if metaBase, err = metaBaseInit(ctx); err != nil {
		err = ref.ErrAddPrintf("ColumnAttributeMapClip", err)
		return
	}
	var res = make(map[string]parDef.ColMetaMapS)
	for _, v := range metaBase.columnMetaMap {
		var key = v.ColumnName
		if _, ok := res[key]; !ok {
			res[key] = v
		}
	}
	result.Result = res
	return
}
